//! # 认证服务配置管理
//!
//! 提供认证服务的配置结构和管理功能。

use serde::{Deserialize, Serialize};
use rustcloud_security::prelude::*;

pub mod auth_config;
pub mod security_config;

// 重新导出主要配置类型
pub use auth_config::AuthConfig;
pub use security_config::SecurityConfig;

/// 完整的认证配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RustCloudAuthConfig {
    /// 认证配置
    pub auth: AuthConfig,
    /// 安全配置
    pub security: SecurityConfig,
    /// 提供者配置
    pub providers: crate::providers::ProvidersConfig,
    /// 服务配置
    pub service: ServiceConfig,
}

/// 服务配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceConfig {
    /// 服务名称
    pub name: String,
    /// 服务版本
    pub version: String,
    /// 监听地址
    pub listen_addr: String,
    /// 监听端口
    pub listen_port: u16,
    /// 是否启用TLS
    pub tls_enabled: bool,
    /// TLS配置
    pub tls_config: Option<TlsConfig>,
    /// 性能配置
    pub performance: PerformanceConfig,
}

/// TLS配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TlsConfig {
    /// 证书文件路径
    pub cert_file: String,
    /// 私钥文件路径
    pub key_file: String,
    /// CA证书文件路径（用于客户端证书验证）
    pub ca_file: Option<String>,
    /// 是否要求客户端证书
    pub require_client_cert: bool,
}

/// 性能配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceConfig {
    /// 最大并发请求数
    pub max_concurrent_requests: u32,
    /// 请求超时时间（秒）
    pub request_timeout_seconds: u64,
    /// 连接池大小
    pub connection_pool_size: u32,
    /// 是否启用缓存
    pub cache_enabled: bool,
    /// 缓存配置
    pub cache_config: Option<CacheConfig>,
}

/// 缓存配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheConfig {
    /// 缓存类型（memory, redis等）
    pub cache_type: String,
    /// 缓存TTL（秒）
    pub ttl_seconds: u64,
    /// 最大缓存条目数
    pub max_entries: u64,
    /// Redis连接字符串（如果使用Redis缓存）
    pub redis_url: Option<String>,
}

impl Default for RustCloudAuthConfig {
    fn default() -> Self {
        Self {
            auth: AuthConfig::default(),
            security: SecurityConfig::default(),
            providers: crate::providers::ProvidersConfig::default(),
            service: ServiceConfig::default(),
        }
    }
}

impl Default for ServiceConfig {
    fn default() -> Self {
        Self {
            name: "rustcloud-auth".to_string(),
            version: "0.1.0".to_string(),
            listen_addr: "0.0.0.0".to_string(),
            listen_port: 8080,
            tls_enabled: false,
            tls_config: None,
            performance: PerformanceConfig::default(),
        }
    }
}

impl Default for PerformanceConfig {
    fn default() -> Self {
        Self {
            max_concurrent_requests: 1000,
            request_timeout_seconds: 30,
            connection_pool_size: 10,
            cache_enabled: true,
            cache_config: Some(CacheConfig::default()),
        }
    }
}

impl Default for CacheConfig {
    fn default() -> Self {
        Self {
            cache_type: "memory".to_string(),
            ttl_seconds: 300, // 5分钟
            max_entries: 10000,
            redis_url: None,
        }
    }
}

/// 配置加载器
pub struct ConfigLoader;

impl ConfigLoader {
    /// 从文件加载配置
    pub fn load_from_file(path: &str) -> Result<RustCloudAuthConfig, Box<dyn std::error::Error>> {
        let content = std::fs::read_to_string(path)?;
        
        if path.ends_with(".toml") {
            Ok(toml::from_str(&content)?)
        } else if path.ends_with(".json") {
            Ok(serde_json::from_str(&content)?)
        } else {
            Err("Unsupported config file format. Use .toml or .json".into())
        }
    }

    /// 从环境变量加载配置
    pub fn load_from_env() -> RustCloudAuthConfig {
        let mut config = RustCloudAuthConfig::default();

        // 服务配置
        if let Ok(name) = std::env::var("RUSTCLOUD_AUTH_SERVICE_NAME") {
            config.service.name = name;
        }
        if let Ok(addr) = std::env::var("RUSTCLOUD_AUTH_LISTEN_ADDR") {
            config.service.listen_addr = addr;
        }
        if let Ok(port) = std::env::var("RUSTCLOUD_AUTH_LISTEN_PORT") {
            if let Ok(port_num) = port.parse::<u16>() {
                config.service.listen_port = port_num;
            }
        }

        // TLS配置
        if let Ok(tls_enabled) = std::env::var("RUSTCLOUD_AUTH_TLS_ENABLED") {
            config.service.tls_enabled = tls_enabled.to_lowercase() == "true";
        }

        // JWT配置
        if let Ok(jwt_secret) = std::env::var("RUSTCLOUD_AUTH_JWT_SECRET") {
            // 更新JWT提供者配置中的密钥
            for provider in &mut config.providers.providers {
                if provider.name == "jwt" {
                    if let Some(config_obj) = provider.config.as_object_mut() {
                        config_obj.insert("secret".to_string(), serde_json::Value::String(jwt_secret.clone()));
                    }
                }
            }
        }

        config
    }

    /// 合并配置（环境变量覆盖文件配置）
    pub fn load_with_overrides(file_path: Option<&str>) -> Result<RustCloudAuthConfig, Box<dyn std::error::Error>> {
        let mut config = if let Some(path) = file_path {
            Self::load_from_file(path)?
        } else {
            RustCloudAuthConfig::default()
        };

        // 使用环境变量覆盖
        let env_config = Self::load_from_env();
        Self::merge_configs(&mut config, env_config);

        Ok(config)
    }

    /// 合并两个配置，第二个配置的值会覆盖第一个
    fn merge_configs(base: &mut RustCloudAuthConfig, override_config: RustCloudAuthConfig) {
        // 这里实现配置合并逻辑
        // 为简化，我们只合并几个关键字段
        if override_config.service.name != "rustcloud-auth" {
            base.service.name = override_config.service.name;
        }
        if override_config.service.listen_addr != "0.0.0.0" {
            base.service.listen_addr = override_config.service.listen_addr;
        }
        if override_config.service.listen_port != 8080 {
            base.service.listen_port = override_config.service.listen_port;
        }
    }
}

/// 配置验证器
pub struct ConfigValidator;

impl ConfigValidator {
    /// 验证配置的有效性
    pub fn validate(config: &RustCloudAuthConfig) -> Result<(), Vec<String>> {
        let mut errors = Vec::new();

        // 验证服务配置
        if config.service.name.is_empty() {
            errors.push("Service name cannot be empty".to_string());
        }

        if config.service.listen_port == 0 {
            errors.push("Listen port must be greater than 0".to_string());
        }

        // 验证提供者配置
        if config.providers.providers.is_empty() {
            errors.push("At least one authentication provider must be configured".to_string());
        }

        let enabled_providers: Vec<_> = config.providers.providers
            .iter()
            .filter(|p| p.enabled)
            .collect();

        if enabled_providers.is_empty() {
            errors.push("At least one authentication provider must be enabled".to_string());
        }

        // 验证默认提供者是否存在且启用
        let default_provider_exists = enabled_providers
            .iter()
            .any(|p| p.name == config.providers.default_provider);

        if !default_provider_exists {
            errors.push(format!(
                "Default provider '{}' is not found or not enabled",
                config.providers.default_provider
            ));
        }

        // 验证TLS配置
        if config.service.tls_enabled {
            if let Some(tls_config) = &config.service.tls_config {
                if tls_config.cert_file.is_empty() {
                    errors.push("TLS cert file path cannot be empty when TLS is enabled".to_string());
                }
                if tls_config.key_file.is_empty() {
                    errors.push("TLS key file path cannot be empty when TLS is enabled".to_string());
                }
            } else {
                errors.push("TLS config must be provided when TLS is enabled".to_string());
            }
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_config() {
        let config = RustCloudAuthConfig::default();
        assert_eq!(config.service.name, "rustcloud-auth");
        assert_eq!(config.service.listen_port, 8080);
        assert!(!config.service.tls_enabled);
        assert!(!config.providers.providers.is_empty());
    }

    #[test]
    fn test_config_validation_success() {
        let config = RustCloudAuthConfig::default();
        assert!(ConfigValidator::validate(&config).is_ok());
    }

    #[test]
    fn test_config_validation_failure() {
        let mut config = RustCloudAuthConfig::default();
        config.service.name = "".to_string();
        config.service.listen_port = 0;
        
        let result = ConfigValidator::validate(&config);
        assert!(result.is_err());
        
        let errors = result.unwrap_err();
        assert!(!errors.is_empty());
        assert!(errors.iter().any(|e| e.contains("Service name cannot be empty")));
        assert!(errors.iter().any(|e| e.contains("Listen port must be greater than 0")));
    }

    #[test]
    fn test_config_serialization() {
        let config = RustCloudAuthConfig::default();
        
        // 测试JSON序列化
        let json = serde_json::to_string(&config).unwrap();
        let deserialized: RustCloudAuthConfig = serde_json::from_str(&json).unwrap();
        assert_eq!(config.service.name, deserialized.service.name);

        // 测试TOML序列化
        let toml = toml::to_string(&config).unwrap();
        let deserialized_toml: RustCloudAuthConfig = toml::from_str(&toml).unwrap();
        assert_eq!(config.service.name, deserialized_toml.service.name);
    }
}